/**
 * ShootingGameCanvas类,代表射击游戏
 * @constructor
 * @param {Object} options ShootingGameCanvas的参数
 * @param {number} [options.level=1] 游戏level,最小为1,最大为6,会根据不同的level生成不同的怪兽数量(搞定)
 * @param {number} [options.totalLevel=6] 游戏总共6关(搞定)
 * @param {number} [options.defaultScores=6] 游戏默认分数
 * @param {function} [options.successCallback] 游戏成功的回调函数(搞定)
 * @param {function} [options.completedCallback] 游戏成功的回调函数(搞定)
 * @param {function} [options.failureCallback] 游戏失败的回调函数(搞定)
 * @param {num} [options.numPerLine=7] 每行多少个怪兽(搞定)
 * @param {num} [options.canvasPadding=30] 画布的间隔(搞定)
 * @param {num} [options.bulletSize=10] 子弹长度(搞定)
 * @param {num} [options.bulletSpeed=10] 子弹移动速度(搞定)
 * @param {num} [options.enemySize=50] 敌人的尺寸(搞定)
 * @param {num} [options.enemyGap=10] 敌人之间的间距(搞定)
 * @param {string} [options.enemyIcon] 怪兽的图像(搞定)
 * @param {string} [options.enemyBoomIcon] 怪兽死亡的图像(搞定)
 * @param {string} [options.enemyDirection=right] 默认敌人一开始向右移动(搞定)
 * @param {string} [options.planeSpeed=5] 飞机每一步移动的距离(搞定)
 * @param {object} [options.planeSize] 飞机的尺寸(搞定)
 * @param {object} [options.planeIcon] 飞机的图像(搞定)
 */
function ShootingGameCanvas(options) {
  // 处理options
  options = Object.assign({}, {
    level: 1,
    totalLevel: 6,
    defaultScores: 0,
    successCallback: function (options) {},
    completedCallback: function(options) {},
    failureCallback: function (options) {},
    numPerLine: 1,
    canvasPadding: 30,
    bulletSize: 10,
    bulletSpeed: 10,
    enemySize: 50,
    enemyGap: 10,
    enemyIcon: './img/enemy.png',
    enemyBoomIcon: './img/boom.png',
    enemyDirection: 'right',
    planeSpeed: 5,
    planeSize: {
      width: 60,
      height: 100
    },
    planeIcon: './img/plane.png'
  }, options);
  // 继承属性 
  BaseCanvas.call(this, options);
  this.level = options.level;
  this.totalLevel = options.totalLevel;
  this.defaultScores = options.defaultScores;
  this.successCallback = options.successCallback;
  this.completedCallback = options.completedCallback;
  this.failureCallback = options.failureCallback;
  this.canvasPadding = options.canvasPadding;
  this.numPerLine = options.numPerLine;
  this.bulletSize = options.bulletSize;
  this.bulletSpeed = options.bulletSpeed;
  this.enemyGap = options.enemyGap;
  this.enemySize = options.enemySize;
  this.enemyIcon = options.enemyIcon;
  this.enemyBoomIcon = options.enemyBoomIcon;
  this.enemyDirection = options.enemyDirection;
  this.planeSpeed = options.planeSpeed;
  this.planeSize = options.planeSize;
  this.planeIcon = options.planeIcon;
  // 所有的canvasElement
  this.allCanvasElements = {};
  // 维护按键状态,因为空格键和方向键需要同时按下
  this.keys = {
    Space: false,
    ArrowLeft: false,
    ArrowRight: false,
  }
  // 游戏状态,可以为playing|success|failed|all-success
  this.status = 'playing';
  // 当前分数
  this.scores = this.defaultScores;
  // 目标分数
  this.targetScores = Infinity;
  // 处理事件处理程序的this
  this.handleKeyboardEvent = this.handleKeyboardEvent.bind(this);
  // 初始化处理
  this.init();
  console.log('初始化第'+this.level+'关游戏成功');
}

inheritPrototype(ShootingGameCanvas, BaseCanvas);

/**
 * init方法
 */
ShootingGameCanvas.prototype.init = function () {
  // 初始化怪兽组元素
  var monsterGroup = new MonsterGroupCanvasElement({
    monsterSize: this.enemySize,
    monsterImgUrl: this.enemyIcon,
    monsterImgDeadUrl: this.enemyBoomIcon,
    cols: this.numPerLine,
    rows: this.level,
    colSpan: this.enemyGap,
    rowSpan: this.enemyGap,
    // boundaryCoordinates: [30, 30, 670, 470],
    boundaryCoordinates: [this.canvasPadding, this.canvasPadding, this.canvas.width - this.canvasPadding, this.canvas.height - this.canvasPadding - this.planeSize.height],
    startDirection: this.enemyDirection
  });
  // 初始化飞机元素
  var fighter = new FighterCanvasElement({
    x: this.canvas.width / 2 - 60 / 2,
    y: this.canvas.height - 30 - 100,
    vx: this.planeSpeed,
    imgSrc: this.planeIcon,
    width: this.planeSize.width,
    height: this.planeSize.height,
    // boundaryCoordinates: [30, 470, 670, 570],
    boundaryCoordinates: [this.canvasPadding, this.canvas.height - this.canvasPadding - this.planeSize.height, this.canvas.width - this.canvasPadding, this.canvas.height - this.canvasPadding],
    bulletSize: this.bulletSize,
    bulletSpeed: this.bulletSpeed
  });
  // 初始化分数元素
  var score = new ScoreCanvasElement({
    num: this.scores
  });
  // 初始化allCanvasElements
  this.allCanvasElements = {
    monsterGroup: monsterGroup,
    fighter: fighter,
    score: score
  }
  // 初始化目标分数
  this.targetScores = this.defaultScores + monsterGroup.monsters.length;
  // 绑定事件
  this.bindEvent();
}

/**
 * afterDraw方法,主要用于修改各元素的参数.修改参数的操作都放在afterDraw里面会有利于提高性能
 * @override
 */
ShootingGameCanvas.prototype.afterDraw = function () {
  // 一些快速引用
  var score = this.allCanvasElements.score;
  var fighter = this.allCanvasElements.fighter;
  var monsterGroup = this.allCanvasElements.monsterGroup;

  // 判断游戏状态
  if (this.status === 'success') {
    this.destroy();
    this.successCallback({
      level: this.level,
      scores: this.scores,
      nextLevel: this.level === this.totalLevel ? false : this.level + 1
    });
    console.log('游戏成功',{
      level: this.level,
      scores: this.scores,
      nextLevel: this.level === this.totalLevel ? false : this.level + 1
    });
  }else if(this.status === 'failed'){
    this.destroy();
    this.failureCallback({
      level: this.level,
      scores: this.scores,
      targetScores: this.targetScores
    });
    console.log('游戏失败',{
      level: this.level,
      scores: this.scores,
      targetScores: this.targetScores
    });
  }else if(this.status==='all-success') {
    this.destroy();
    this.completedCallback({
      level: this.level,
      totalLevel: this.totalLevel,
      scores: this.scores,
    });
    console.log('全部完成',{
      level: this.level,
      totalLevel: this.totalLevel,
      scores: this.scores,
    });
  }

  // 判断按键
  if (this.keys.Space) {
    // 射击
    fighter.shoot();
  }
  // 不是左就是右移动
  if (this.keys.ArrowLeft) {
    fighter.move('left');
    fighter.boundaryRestrict();
  } else if (this.keys.ArrowRight) {
    fighter.move('right');
    fighter.boundaryRestrict();
  }

  // monsterGroup进行碰撞检测
  monsterGroup.monsters.forEach(function (monster) {
    if (monster.dead) {
      // 如果怪兽已经死亡,则销毁,且不用对已经死亡的怪兽进行碰撞检测
      monster.destroy();
    } else {
      fighter.bullets.forEach(function (bullet) {
        if (bullet.collisionDetection(monster)) {
          // 碰撞了
          monsterFilterFlag = false;
          // 子弹销毁
          bullet.destroy();
          // 标记怪兽死亡
          monster.dead = true;
          // 更新分数
          score.num += 1;
        }
      });
    }
  });

  // 对monsterGroup进行边界检测
  var boundaryRestrictFlag = monsterGroup.boundaryRestrict();
  if (boundaryRestrictFlag) {
    if (boundaryRestrictFlag.bottom) {
      // 游戏结束了
      monsterGroup.monstersDirection = undefined;
      // 更新状态
      this.status = 'failed';
    } else if (boundaryRestrictFlag.left) {
      if (monsterGroup.monstersDirection !== 'down') {
        monsterGroup.monstersDirection = 'down';
      } else {
        monsterGroup.monstersDirection = 'right';
      }
    } else if (boundaryRestrictFlag.right) {
      if (monsterGroup.monstersDirection !== 'down') {
        monsterGroup.monstersDirection = 'down';
      } else {
        monsterGroup.monstersDirection = 'left';
      }
    }
  }

  // 更新分数
  this.scores = score.num;
  // 更新状态
  if (this.scores === this.targetScores) {
    if(this.level === this.totalLevel) {
      this.status = 'all-success';
    }else {
      this.status = 'success';
    }
    
  }
}

/**
 * destroy方法,移除事件监听,清空画布等操作
 * @override
 */
ShootingGameCanvas.prototype.destroy = function () {
  console.log('ShootingGameCanvas destroy');
  // 移除事件监听
  this.removeEvent();
  // 取消循环绘制
  this.cancelRun();
  // 清空画布
  this.clear();
}

/**
 * handleKeyboardEvent 键盘事件的handle
 * @param {object} e 
 */
ShootingGameCanvas.prototype.handleKeyboardEvent = function (e) {
  var key = e.keyCode || e.which || e.charCode;
  var type = e.type;

  if (['keydown', 'keypress'].indexOf(type) !== -1) {
    // 判断按键
    switch (key) {
      // 左键
      case 37:
        this.keys.ArrowLeft = true;
        this.keys.ArrowRight = false;
        break;
        // 右键
      case 39:
        this.keys.ArrowLeft = false;
        this.keys.ArrowRight = true;
        break;
        // 空格键
      case 32:
        this.keys.Space = true;
        break;
      default:
        break;
    }
  }
  if (['keyup'].indexOf(type) !== -1) {
    // 判断按键
    switch (key) {
      // 左键
      case 37:
        this.keys.ArrowLeft = false;
        break;
        // 右键
      case 39:
        this.keys.ArrowRight = false;
        break;
        // 空格键
      case 32:
        this.keys.Space = false;
        break;
      default:
        break;
    }
  }
};

/**
 * bindEvent方法,添加各种事件,要注意在destory的时候销毁这些事件
 */
ShootingGameCanvas.prototype.bindEvent = function () {
  // 监听keydown
  // document.addEventListener('keypress', this.handleKeyDown);
  document.addEventListener('keydown', this.handleKeyboardEvent);
  document.addEventListener('keypress', this.handleKeyboardEvent);
  document.addEventListener('keyup', this.handleKeyboardEvent);
}

/**
 * removeEvent方法,移除各种事件,避免内存泄露
 */
ShootingGameCanvas.prototype.removeEvent = function () {
  document.removeEventListener('keydown', this.handleKeyboardEvent);
  document.removeEventListener('keypress', this.handleKeyboardEvent);
  document.removeEventListener('keyup', this.handleKeyboardEvent);
}